﻿/// <reference path="../../../typings/index.d.ts" />
import *as redis from 'ioredis'
export class Redis数据库 extends redis {
    constructor(选项:redis.RedisOptions) {
        super(选项)
        this.on('error', (err) => {
            console.log('数据库错误: ',err)
        })
    }
    public 选择(库: number) {
        this.select(库)
    }
    public 发布(频道: string, 数据: string, 回调?: (err: void | Error, 结果: number) => void) {
        if (回调) {
            this.publish(频道, 数据, (err, 结果) => {
                回调(err, 结果)
            })
        } else {
            let 结果 = this.publish(频道, 数据)
            return 结果
        }
    }
    ///接收到信息的订阅者数量


    public 同步发布(频道: string, 数据: string) {
        return new Promise<number>((成功, 失败) => {
            try {
                this.publish(频道, 数据, (err, 值) => {
                    if (err)
                        失败(err)
                    成功(值)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///接收到的信息
    public 同步订阅(...频道: string[]) {
        return new Promise<string>((成功, 失败) => {
            try {
                this.subscribe(频道, (err, 值) => {
                    if (err)
                        失败(err)
                    成功(值)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    public 订阅(回调?: (err: void | Error, 结果: string) => void, ...频道: string[]) {
        if (回调) {
            this.subscribe(...频道, (err, 结果) => {
                回调(err, 结果)
            })
        } else {
            let 结果 = this.subscribe(...频道)
            return 结果
        }
    }
    public 同步键值存值 = (键: string, 值: string) => {
        return new Promise<string>((成功, 失败) => {
            try {
                this.set(键, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    public 同步键值存多值 = (...键值: string[]) => {
        return new Promise<boolean>((成功, 失败) => {
            try {
                this.mset(...键值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///设置新的值,返回旧的值
    public 同步键值更新值 = (键: string, 值: string) => {
        return new Promise<string>((成功, 失败) => {
            try {
                this.getset(键, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///返回删除的数量
    public 同步键值删除键 = (...键: string[]) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.del(...键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    //返回键的值,不存在返回 nli,不是字符串返回错误

    public 同步键值读值 = (键: string) => {
        return new Promise<any>((成功, 失败) => {
            try {
                this.get(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    

    public 同步键值追加值 = (键: string, 值: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.append(键, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    
    ///一个包含所有给定 key 的值的列表
    public 同步键值读多个键值 = (...键值: string[]) => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.mget(...键值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///被添加到集合中的新元素的数量,不包括被忽略的元素
    public 同步集合插入键值 = (...键值: string[]) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.sadd(...键值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })

    }

    ///集合的数量. 当集合 key 不存在时,返回 0 
    public 同步集合取成员数量 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.scard(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///返回1是,0否
    public 同步集合判断是否为成员 = (键: string, 值: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.sismember(键, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    /// 命令返回集合中的所有的成员. 不存在的集合 key 被视为空集合.
    public 同步集合读取全部成员 = (键: string) => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.smembers(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///被成功移除的元素的数量,不包括被忽略的元素.
    public 同步集合删除成员 = (键: string, ...成员: string[]) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.srem(键, ...成员, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///被成功添加的新成员的数量,不包括那些被更新的\已经存在的成员.
    public 同步有序集合添加成员 = (键: string, 成员: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.zadd(键, 0, 成员, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///当 key 存在且是有序集类型时,返回有序集的基数.当 key 不存在时,返回 0
    public 同步有序集合读取成员数量 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.zcard(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///如果成员是有序集 key 的成员,返回 member 的排名. 如果成员不是有序集 key 的成员,返回 nil.
    public 同步有序集合取成员索引 = (键: string, 成员: string) => {
        return new Promise<number | void>((成功, 失败) => {
            try {
                this.zrank(键, 成员, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///被成功移除的成员的数量,不包括被忽略的成员
    public 同步有序集合删除成员 = (键: string, 成员: string[]) => {
        return new Promise<number | void>((成功, 失败) => {
            try {
                this.zrem(键, ...成员, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///执行 INCR 命令之后 key 的值
    public 同步自增 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.incr(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    public 同步自减 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.decr(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    //执行 DECR 命令之后 key 的值
    public 同步删除键 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.del(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    /**
      * 若 key 存在返回 1,否则返回 0
      * @param 键 string 要检查的 key
      */
    public 同步检查键 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.exists(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    public 同步取所有键 = () => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.keys('*', (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    ///设置成功返回 1 ,失败返回 0
    public 同步设置键过期时间 = (键: string, 毫秒: number) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.pexpire(键, 毫秒, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///当过期时间移除成功时,返回 1. 如果 key 不存在或 key 没有设置过期时间,返回 0 
    public 同步删除键过期时间 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.persist(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///当 key 不存在时,返回 -2 . 当 key 存在但没有设置剩余生存时间时,返回 -1. 否则,以毫秒为单位.
    public 同步返回键剩余过期时间 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.ttl(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    ///改名成功时提示 OK ,失败时候返回一个错误
    public 同步修改键名 = (键: string, 新键: string) => {
        return new Promise<'OK'>((成功, 失败) => {
            try {
                this.rename(键, 新键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }
    /// 返回类型名
    public 同步取键类型 = (键: string, 新键: string) => {
        return new Promise<'none' | 'string' | 'list' | 'set' | 'zset' | 'hash'>((成功, 失败) => {
            try {
                this.type(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果 as 'none' | 'string' | 'list' | 'set' | 'zset' | 'hash')
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    // 哈希表
    public 同步哈希表储存多字段 = (键: string, ...字段与值对: string[]) => {
        return new Promise<any>((成功, 失败) => {
            try {
                this.hmset(键, ...字段与值对, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表读多字段 =(键: string, ...字段: string[]) => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.hmget(键, ...字段, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表全部值 = (键: string) => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.hvals(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表删除字段值 = (键: string, ...字段: string[]) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.hdel(键, ...字段, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表指定字段是否存在 = (键: string, 字段: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.hexists(键, 字段, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表获取指定字段值 = (键: string, 字段: string) => {
        return new Promise<string>((成功, 失败) => {
            try {
                this.hget(键, 字段, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表写入指定字段值 = (键: string, 字段: string, 值: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.hset(键, 字段, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表获取全部字段 = (键: string) => {
        return new Promise<string[]>((成功, 失败) => {
            try {
                this.hkeys(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表获取字段数量 = (键: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.hlen(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表写入不存在字段值 = (键: string, 字段: string, 值: string) => {
        return new Promise<number>((成功, 失败) => {
            try {
                this.hsetnx(键, 字段, 值, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

    public 同步哈希表获取全部字段及值 = (键: string) => {
        return new Promise<{ [key: string]: string }>((成功, 失败) => {
            try {
                this.hgetall(键, (err, 结果) => {
                    if (err)
                        失败(err)
                    成功(结果)
                })
            } catch (err) {
                失败(err)
            }
        })
    }

}